Completed
Push — master ( e0fab0...e45f10 )
by Andres
35s
created

angular.controller(ꞌct_matterꞌ)   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
c 0
b 0
f 0
nc 2
dl 0
loc 12
rs 9.4285
nop 3
1
/**
2
 matter
3
 Component that handles generators, resource creation, isotopes and decay.
4
5
 @namespace Components
6
 */
7
'use strict';
8
9
angular.module('game').component('matter', {
10
  templateUrl: 'views/matter.html',
11
  controller: 'ct_matter',
12
  controllerAs: 'ct'
13
});
14
15
angular.module('game').controller('ct_matter', ['state', 'visibility', 'data', 'util', 'reaction',
16
  function (state, visibility, data, util, reaction) {
17
    let ct = this;
18
    ct.state = state;
19
    ct.data = data;
20
    let buyAmount = [1, 10, 25, 100, 'max'];
21
22
    <%= upgradeFunctions %>
23
24
    /* Proceses the decay of radiactive isotopes. It uses a random draw based on the
25
    half life to decide how many atoms decay, and then spreads them over different
26
    decay forms proportionally. */
27
    function processDecay(player) {
28
      // for each radiactive isotope
29
      for (let i = 0; i < data.radioisotopes.length; i++) {
30
        let resource = data.radioisotopes[i];
31
        if (player.resources[resource].unlocked) {
32
          let element = Object.keys(data.resources[resource].elements)[0];
33
          let number = player.resources[resource].number;
34
          let decay = data.elements[element].isotopes[resource].decay;
35
          let halfLife = decay.half_life;
36
          let exponent = 1/halfLife;
37
          let factor = Math.pow(0.5, exponent);
38
          let totalProduction = Math.floor(number - number * factor);
39
          let remaining = totalProduction;
40
          // and decay products
41
          let highestRatio;
42
          for (let type of Object.values(decay.decay_types)) {
43
            if(!highestRatio || highestRatio.ratio < type.ratio){
44
              highestRatio = type;
45
            }
46
            let production = Math.floor(totalProduction * type.ratio);
47
            // FIXME: this is a hack to fix decay not working if the number of
48
            // neutrons is lower than the decay amount. Fixing starvation
49
            // should fix this one as well
50
            if (type.reaction.reactant && type.reaction.reactant.n) {
51
              production = Math.min(production, player.resources.n.number);
52
            }
53
            reaction.react(production, type.reaction, player);
54
            remaining -= production;
55
          }
56
          reaction.react(remaining, highestRatio.reaction, player);
57
        }
58
      }
59
    }
60
61
    /* Proceses the generation for each element. It generates isotopes with a random
62
    draw proportionally to their probability. */
63
    function processGenerators(player) {
64
      // we will simulate the production of isotopes proportional to their ratio
65
      for (let element in player.elements) {
66
        if (!player.elements[element].unlocked) {
67
          continue;
68
        }
69
        let totalProduction = ct.elementProduction(player, element);
70
        let remaining = totalProduction;
71
        // for each isotope
72
        for (let key in data.elements[element].isotopes) {
73
          let isotope = data.elements[element].isotopes[key];
74
          // we calculate the production proportion
75
          let production = Math.floor(isotope.ratio * totalProduction);
76
77
          // assign the player the produced isotope
78
          player.resources[key].number += production;
79
          if (production > 0 && !player.resources[key].unlocked) {
80
            player.resources[key].unlocked = true;
81
            state.addNew(key);
82
          }
83
          // keep track of the remaining production
84
          remaining -= production;
85
        }
86
        // if there is remaining production, we assign it to the main isotope
87
        let main = data.elements[element].main;
88
        player.resources[main].number += remaining;
89
        if (remaining > 0 && !player.resources[main].unlocked) {
90
          player.resources[main].unlocked = true;
91
          state.addNew(main);
92
        }
93
      }
94
    }
95
96
    function update(player) {
97
      processDecay(player);
98
      processGenerators(player);
99
    }
100
101
    function generatorPrice(name, level) {
102
      return data.generators[name].price * Math.pow(data.constants.GENERATOR_PRICE_INCREASE, level);
103
    }
104
105
    ct.maxCanBuy = function (player, name, element) {
106
      let level = player.elements[element].generators[name];
107
      let i = 0;
108
      let currency = data.elements[element].main;
109
      let price = generatorPrice(name, level);
110
      // we need a loop since we use the ceil operator
111
      while (player.resources[currency].number >= price) {
112
        i++;
113
        price += generatorPrice(name, level + i);
114
      }
115
      return i;
116
    };
117
118
    ct.generatorTotalPrice = function (player, name, element, number) {
119
      if (number === 'max') {
120
        number = ct.maxCanBuy(player, name, element);
121
      }
122
      let level = player.elements[element].generators[name];
123
      let totalPrice = 0;
124
      for (let i = 0; i < number; i++) {
125
        let price = generatorPrice(name, level + i);
126
        totalPrice += Math.ceil(price);
127
      }
128
      return totalPrice;
129
    };
130
131
    ct.buyGenerators = function (player, name, element, number) {
132
      if (number === 'max') {
133
        number = ct.maxCanBuy(player, name, element);
134
      }
135
      let price = this.generatorTotalPrice(player, name, element, number);
136
      let currency = data.elements[element].main;
137
      if (ct.canBuy(player, element, price)) {
138
        player.resources[currency].number -= price;
139
        player.elements[element].generators[name] += number;
140
      }
141
    };
142
143
    ct.canBuy = function (player, element, price) {
144
      let currency = data.elements[element].main;
145
      if (price > player.resources[currency].number) {
146
        return false;
147
      }
148
      return true;
149
    };
150
151
    ct.generatorProduction = function (player, name, element) {
152
      let baseProduction = data.generators[name].power;
153
      return upgradedProduction(player, baseProduction, name, element);
154
    };
155
156
    ct.tierProduction = function (player, name, element) {
157
      let baseProduction = data.generators[name].power *
158
        player.elements[element].generators[name];
159
      return upgradedProduction(player, baseProduction, name, element);
160
    };
161
162
    /* Upgraded production includes upgrades, exotic matter and dark matter. */
163
    function upgradedProduction(player, production, name, element) {
164
      for (let up of data.generators[name].upgrades) {
165
        if (player.elements[element].upgrades[up]) {
166
          let func = data.upgrades[up].function;
167
          production = ct[func](player, production);
168
        }
169
      }
170
      let exotic = data.elements[element].exotic;
171
      production *= (1 + player.resources[exotic].number * data.constants.EXOTIC_POWER) *
172
        (1 + player.resources.dark_matter.number * data.constants.DARK_POWER);
173
      return Math.floor(production);
174
    }
175
176
    ct.elementProduction = function (player, element) {
177
      let total = 0;
178
      for (let tier in data.generators) {
179
        total += ct.tierProduction(player, tier, element);
180
      }
181
      return total;
182
    };
183
184
    ct.visibleGenerators = function (currentElement) {
185
      return visibility.visible(data.generators, isGeneratorVisible, currentElement);
186
    };
187
188
    function isGeneratorVisible(name, currentElement) {
189
      let generator = data.generators[name];
190
      for (let dep of generator.deps) {
191
        if (state.player.elements[currentElement].generators[dep] === 0) {
192
          return false;
193
        }
194
      }
195
196
      return true;
197
    }
198
199
    ct.nextBuyAmount = function () {
200
      state.buyIndex = (state.buyIndex + 1) % buyAmount.length;
201
    };
202
203
    ct.getbuyAmount = function () {
204
      return buyAmount[state.buyIndex];
205
    };
206
207
    state.registerUpdate('matter', update);
208
  }
209
]);
210